package com.gomoku;

import com.common.GameBoard;
import com.common.InputBox;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;

// 主窗口
class MainWindow extends JFrame implements ActionListener, Game.Callback, MouseListener, RivalWindow.Callback, WindowListener {
    private Game mGame;                         // 游戏
    private final JLabel mLabelRivalName;       // "当前对手"标签
    private final JMenuItem mMenuItemDefeat;    // "认输"菜单项
    private final JMenuItem mMenuItemFindUsers; // "寻找其它用户"菜单项
    private final JMenuItem mMenuItemRestart;   // “再来一局"菜单项
    private final RivalWindow mRivalWindow;     // 对手列表窗口

    /**
     * 构造方法。
     */
    public MainWindow() {
        // 设置当单击右上角的X按钮时退出程序
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // 设置窗口标题
        super.setTitle(Const.getString("IDS_APP_NAME"));
        
        // 设置窗口尺寸不能改变
        super.setResizable(false);
        
        // 设置窗口尺寸
        super.setSize(Const.WIDTH, Const.HEIGHT);
        
        // 设置窗口居中
        super.setLocationRelativeTo(null);
        
        // 监听窗口事件
        super.addWindowListener(this);

        // 创建菜单栏
        final JMenuBar mainMenuBar = new JMenuBar();
        super.setJMenuBar(mainMenuBar);
        
        // 创建"游戏"菜单
        final JMenu menuGame = new JMenu(Const.getString("IDS_GAME"));
        mainMenuBar.add(menuGame);
        
        // 创建"寻找其它用户"菜单项
        mMenuItemFindUsers = new JMenuItem(Const.getString("IDS_FIND_USERS"));
        menuGame.add(mMenuItemFindUsers);
        mMenuItemFindUsers.addActionListener(this);
        
        // 创建"认输"菜单项
        mMenuItemDefeat = new JMenuItem(Const.getString("IDS_DEFEAT"));
        menuGame.add(mMenuItemDefeat);
        mMenuItemDefeat.addActionListener(this);
        mMenuItemDefeat.setEnabled(false);
        
        // 创建"再来一局"菜单项
        mMenuItemRestart = new JMenuItem(Const.getString("IDS_RESTART"));
        menuGame.add(mMenuItemRestart);
        mMenuItemRestart.addActionListener(this);
        mMenuItemRestart.setEnabled(false);
        
        // 创建状态栏
        mLabelRivalName = new JLabel();
        mLabelRivalName.setText(Const.getString("IDS_CURRENT_RIVAL"));
        final JToolBar statusBar = new JToolBar();
        statusBar.setLayout(new GridLayout(1, 1));
        statusBar.setFloatable(false);
        super.add(statusBar, BorderLayout.SOUTH);
        statusBar.add(mLabelRivalName);
        
        // 创建对手列表窗口
        mRivalWindow = new RivalWindow(this);

        // 创建游戏区域
        final GameBoard gameBoard = new GameBoard(this, 0, 0, Const.GAME_BOARD_WIDTH, Const.GAME_BOARD_HEIGHT);
        gameBoard.addMouseListener(this);
        
        // 创建游戏
        try {
            mGame = new Game(this, gameBoard.getDrawer(), gameBoard);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, Const.getString("IDS_NETWORK_ERROR"), " ", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        
        // 登录
        this.logon();
    }

    /**
     * 菜单项的单击响应方法。
     * @param e 事件相关信息
     */
    public void actionPerformed(ActionEvent e) {
        final Object source = e.getSource();
        if (source == mMenuItemFindUsers) {
            this.onMenuItemFindUsersClicked();
        } else if (source == mMenuItemDefeat) {
            this.onMenuItemDefeatClicked();
        } else if (source == mMenuItemRestart) {
            this.onMenuItemRestartClicked();
        }
    }
    
    /**
     * 登录。
     */
    public void logon() {
        final String username = InputBox.getStringValue(Const.getString("IDS_INPUT_USERNAME"), this, "");
        if (username == null || username.isEmpty()) {
            mGame.close();
            System.exit(0);
        }
        mGame.logon(username);
    }
    
    /**
     * 单击游戏区域事件的响应方法。
     * @param e 事件相关信息
     */
    public void mouseClicked(MouseEvent e) {
        mGame.onGameBoardClicked(e.getX(), e.getY());
    }

    public void mouseEntered(MouseEvent mouseevent) {
    }

    public void mouseExited(MouseEvent mouseevent) {
    }

    public void mousePressed(MouseEvent mouseevent) {
    }

    public void mouseReleased(MouseEvent mouseevent) {
    }

    /**
     * 游戏结束事件的响应方法。
     * @param reason    结束原因
     */
    @Override
    public void onGameOver(GameOverReason reason) {
        // 设置菜单项
        mMenuItemFindUsers.setEnabled(true);
        mMenuItemDefeat.setEnabled(false);
        mMenuItemRestart.setEnabled(true);
        
        // 显示提示信息
        String text = "";
        switch (reason) {
            case LOST:
                text = Const.getString("IDS_LOST");
                break;
            case RIVAL_ADMIT:
                text = Const.getString("IDS_RIVAL_ADMIT");
                break;
            case SELF_ADMIT:
                text = Const.getString("IDS_SELF_ADMIT");
                break;
            case WON:
                text = Const.getString("IDS_WON");
                break;
        }
        JOptionPane.showMessageDialog(this, text, " ", JOptionPane.INFORMATION_MESSAGE);
    }
    
    /**
     * 游戏开始事件的响应方法。
     * @param rivalName 对手的名字
     */
    @Override
    public void onGameStart(String rivalName) {
        // 隐藏对手列表窗口
        mRivalWindow.setVisible(false);
        
        // 设置菜单项
        mMenuItemFindUsers.setEnabled(false);
        mMenuItemDefeat.setEnabled(true);
        mMenuItemRestart.setEnabled(false);
        
        // 显示对手的名字
        mLabelRivalName.setText(Const.getString("IDS_CURRENT_RIVAL") + rivalName);
    }

    /**
     * 得到寻找用户结果事件的响应方法。
     * @param result    结果
     */
    @Override
    public void onGetFindUsersResult(FindUsersResult result) {
        if (result.mUsernameList != null) {
            mRivalWindow.setUsernameList(result.mUsernameList);
            mRivalWindow.setVisible(true);
        }
    }

    /**
     * 得到挑战请求事件的响应方法。
     * @param rivalName 对手的名字
     */
    @Override
    public void onGetInviteRequest(String rivalName) {
        final String question = rivalName + Const.getString("IDS_INVITE");
        boolean accept = JOptionPane.showConfirmDialog(this, question, " ", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
        mGame.acceptInvite(rivalName, accept);
    }

    /**
     * 得到挑战结果事件的响应方法。
     * @param rivalName 对手的名字
     * @param accept    接受挑战则为 true，否则为 false
     */
    @Override
    public void onGetInviteResult(String rivalName, boolean accept) {
        String information = rivalName;
        if (accept) {
            information += Const.getString("IDS_ACCEPT");
        } else {
            information += Const.getString("IDS_REFUSE");
        }
        JOptionPane.showMessageDialog(this, information, " ", JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * 得到登录结果事件的响应方法。
     * @param succeeded 登录结果
     */
    @Override
    public void onGetLogonResult(boolean succeeded) {
        if (succeeded) {
            JOptionPane.showMessageDialog(this, Const.getString("IDS_LOGON_SUCCEEDED"), " ", JOptionPane.INFORMATION_MESSAGE);
        } else {
            JOptionPane.showMessageDialog(this, Const.getString("IDS_LOGON_FAILED"), " ", JOptionPane.INFORMATION_MESSAGE);
            this.logon();
        }
    }

    /**
     * 获取对手的名字事件的响应方法。
     * @param rivalName 对手的名字
     */
    @Override
    public void onGetRivalName(String rivalName) {
        mGame.invite(rivalName);
    }

    /**
     * "认输"菜单项的单击响应方法。
     */
    private void onMenuItemDefeatClicked() {
        mGame.defeat();
    }
    
    /**
     * "寻找其它用户"菜单项的单击响应方法。
     */
    private void onMenuItemFindUsersClicked() {
        mGame.findUsers();
    }

    /**
     * "再来一局"菜单项的单击响应方法。
     */
    private void onMenuItemRestartClicked() {
        mGame.restart();
    }

    /**
     * 对手退出游戏事件的响应方法。
     * @param escape    对手逃跑则为 true，正常退出则为 false
     * @param rivalName 对手的名字
     */
    @Override
    public void onRivalQuitGame(boolean escape, String rivalName) {
        // 设置菜单项
        mMenuItemFindUsers.setEnabled(true);
        mMenuItemDefeat.setEnabled(false);
        mMenuItemRestart.setEnabled(false);
        
        // 设置状态栏
        mLabelRivalName.setText(Const.getString("IDS_CURRENT_RIVAL"));
        
        // 显示提示信息
        String text = rivalName;
        if (escape) {
            text += Const.getString("IDS_RIVAL_ESCAPE");
        } else {
            text += Const.getString("IDS_RIVAL_QUIT");
        }
        JOptionPane.showMessageDialog(this, text, " ", JOptionPane.INFORMATION_MESSAGE);
    }
    
    @Override
    public void windowActivated(WindowEvent e) {
    }
    
    @Override
    public void windowClosed(WindowEvent e) {
    }
    
    /**
     * 窗口关闭中事件的响应方法。
     * @param e 事件相关信息
     */
    @Override
    public void windowClosing(WindowEvent e) {
        // 关闭游戏
        mGame.close();
    }
    
    @Override
    public void windowDeactivated(WindowEvent e) {
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
    }
    
    @Override
    public void windowIconified(WindowEvent e) {
    }
    
    @Override
    public void windowOpened(WindowEvent e) {
    }
}
